#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct sided{
    int qd;
    int target;
    int value;
};
struct jld{
    int point;
    int jl;
};
struct compare{
    bool operator()(jld a,jld b){
        return a.jl>b.jl;
    }
};
vector<sided>side[200002];
int visited_node[200002]; 
int w[200002];
int find_min(int n){
    int min_dist = 0x3f3f3f3f;
    int min_node = -1;
    for(int i = 0; i < n; i++){ // 从0开始，包含源点
        if(!visited_node[i] && w[i] < min_dist){
            min_dist = w[i];
            min_node = i;
        }
    }
    return min_node;
}
priority_queue<jld,vector<jld>,compare> q;
int main(){
    int n,e;
    cin>>n>>e;
    for(int i=1;i<=e;i++){
        int a,b,c;
        cin>>a>>b>>c;
        sided node;
        node.target=b;
        node.value=c;
        node.qd=a;
        side[a].push_back(node);
    }
    for(int i=1;i<n;i++){
        w[i]=0x3f3f3f3f;
    }
    jld node;
    node.jl=0;
    node.point=0;
    q.push(node);
    while(!q.empty()){
        jld front=q.top();
        q.pop();
        if(visited_node[front.point])continue;
        visited_node[front.point]=1;//出队时才能更新。
        for(int i=0;i<side[front.point].size();i++){
            if(!visited_node[side[front.point][i].target]&&w[front.point]+side[front.point][i].value<w[side[front.point][i].target]){
                w[side[front.point][i].target]=w[front.point]+side[front.point][i].value;
                jld node;
                node.jl=w[side[front.point][i].target];
                node.point=side[front.point][i].target;
                q.push(node);
            }
        }
    }
    for(int i=1;i<n;i++)
    if(w[i]<0x3f3f3f3f)cout<<w[i]<<" ";
    return 0;
}
//dj 初始化所有点无穷大。
//visited设置访问点。
//原点置0
//优先队列取点，访问则跳过。
//拓展没访问过的点。
